﻿using iTool.Cloud.Center.Model;

using Newtonsoft.Json;

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;

namespace iTool.Cloud.Center.ServiceProvider.StorageProvider
{
    internal class iStorageMembershipMaster
    {
        #region static
        [JsonIgnore]
        static object _LockClusterMemberships;
        [JsonIgnore]
        static ConcurrentDictionary<string, iStorageMembershipMaster> ClusterMemberships { get; set; }
        static iStorageMembershipMaster()
        {
            _LockClusterMemberships = new object();
            ClusterMemberships = new ConcurrentDictionary<string, iStorageMembershipMaster>();
        }
        internal static iStorageMembershipMaster GetStorageMasterProvide(string cluster)
        {
            if (ClusterMemberships.TryGetValue(cluster, out iStorageMembershipMaster iStorage))
            {
                return iStorage;
            }

            lock (_LockClusterMemberships)
            {
                if (ClusterMemberships.TryGetValue(cluster, out iStorage))
                {
                    return iStorage;
                }
                else
                {
                    var keyValue = StorageProvider.iStorage.GetKeyValue(cluster, "Membership");

                    iStorage = new iStorageMembershipMaster();

                    if (!string.IsNullOrEmpty(keyValue.Value))
                    {
                        iStorage = JsonConvert.DeserializeObject<iStorageMembershipMaster>(keyValue.Value);
                    }

                    iStorage.Cluster = cluster;
                    iStorage.ClusterTableVersionOptions = iStorage.ClusterTableVersionOptions ?? new ClusterTableVersionOptions();
                    iStorage.Memberships = iStorage.Memberships ?? new ConcurrentDictionary<string, MembershipOptions>();

                    ClusterMemberships.TryAdd(cluster, iStorage);

                    return iStorage;
                }
            }
        }
        #endregion

        [JsonIgnore]
        internal Subject<bool> _subject;
        [JsonIgnore]
        internal string Cluster { get; set; }

        public ConcurrentDictionary<string, MembershipOptions> Memberships { get; set; }
        public ClusterTableVersionOptions ClusterTableVersionOptions { get; set; }

        internal void StartSubjecter()
        {
            if (_subject == null)
            {
                // 计划任务
                _subject = new Subject<bool>();
                _subject.Buffer(TimeSpan.FromSeconds(10), 30) // 1分钟 或者 30 条
                    .Where(x => x.Count > 0)
                    .Select(list => Observable.FromAsync(() => iStorage.BatchWriteAsync(Cluster, "Membership", this)))
                    .Concat()
                    .Subscribe();
            }
        }
        internal void Upsert()
        {
            _subject.OnNext(true);
        }
    }

}
